from enum import Enum
from typing import Optional, List, Union, Dict

from pydantic import BaseModel

START_ROW_OF_DATA = 2
NO_UNIT_PRICE_STATUS = [None, 0, "无", "/", "／", "-"]
EXCEPTION_CODE = {0: "无报价", -1: "报价异常", -2: "产品异常或冗余"}


class TableType(Enum):
    SUMMARY = "summary"
    BID = "bid"


class ProductDetail(BaseModel):
    """
    产品信息类，包含具体的产品字段。
    """

    order_num: Union[int, str]
    code: Optional[str]
    name: str
    spec: Union[int, str]
    unit: Optional[str]
    required_brand: Optional[str]


class OfferDetail(BaseModel):
    """
    报价信息类，包含具体的报价字段。
    """

    unit_price: Union[float, int]
    brand: Optional[str]


class Offer(BaseModel):
    supplier: str
    key_price: Union[float, int]
    is_bargaining: bool
    detail: Optional[OfferDetail]


class ExceptionOfferDetail(BaseModel):
    unit_price: Optional[Union[float, int, str]]
    brand: Optional[str]


class ExceptionOffer(BaseModel):
    status: int
    supplier: str
    key_price: Optional[Union[float, int, str]]
    is_bargaining: bool
    detail: Optional[ExceptionOfferDetail]


class BaseProduct(BaseModel):
    key_name: str
    key_spec: Union[int, str]
    detail: ProductDetail


class SummaryProduct(BaseProduct):
    """
    汇总表产品 - 包含多个报价和最低价信息
    """

    offers: List[Union[Offer, ExceptionOffer]] = []

    @property
    def get_lowest_offer(self) -> Optional[Offer]:
        normal_offers = [offer for offer in self.offers if isinstance(offer, Offer)]
        if not normal_offers:
            return None
        return min(normal_offers, key=lambda offer: offer.key_price or float("inf"))

    @property
    def calculated_difference_between_each_and_lowest(
        self,
    ) -> Dict[str, Union[float, int]]:
        lowest_offer = self.get_lowest_offer
        if not lowest_offer:
            return {}
        return {
            offer.supplier: (offer.key_price - lowest_offer.key_price)
            for offer in self.offers
            if isinstance(offer, Offer)
        }


class BidProduct(BaseProduct):
    offer: Union[Offer, ExceptionOffer]


class BaseTable(BaseModel):
    table_name: str
    table_type: TableType


class ExceptionProduct(BaseProduct):
    # CODE = -2 # 产品异常或冗余
    offer: Optional[Union[Offer, ExceptionOffer]]


class SummaryTable(BaseTable):
    table_type: TableType = TableType.SUMMARY
    suppliers: List[str] = []  # header
    suppliers_with_bargaining: List[str] = []  # 二次议价新增
    products: List[SummaryProduct] = []
    exceptions: List[ExceptionProduct] = []


class BidTable(BaseTable):
    table_type: TableType = TableType.BID
    supplier: str  # 投标供应商名称
    products: List[BidProduct] = []


example = SummaryTable(
    table_name="PPR管阀",
    products=[
        SummaryProduct(
            key_name="产品1",
            key_spec="规格1",
            detail=ProductDetail(
                order_num=1,
                code="001",
                name="产品1",
                spec="规格1",
                unit="个",
                required_brand="品牌A",
            ),
            offers=[
                Offer(
                    supplier="供应商A",
                    key_price=10.1,
                    is_bargaining=False,
                    detail=OfferDetail(unit_price=10.1, brand="品牌A", remark="备注A"),
                ),
                Offer(
                    supplier="供应商B",
                    key_price=9.8,
                    is_bargaining=False,
                    detail=OfferDetail(unit_price=9.8, brand="品牌B", remark=None),
                ),
                Offer(
                    supplier="供应商B",
                    key_price=9.5,
                    is_bargaining=True,
                    detail=OfferDetail(unit_price=9.5, brand="品牌B", remark="议价"),
                ),
                ExceptionOffer(
                    status=-1,
                    supplier="供应商C",
                    key_price="大粪",
                    is_bargaining=False,
                    detail=ExceptionOfferDetail(
                        unit_price="大粪", brand=None, remark="报价异常"
                    ),
                ),
            ],
        ),
    ],
    suppliers=["供应商A", "供应商B", "供应商C"],
)
